#include <myprintf.h>
#include "ec600.h"
#include "cmsis_os2.h"
#include "usart.h"
#include "string.h"
#include "ctype.h"
#include "stdarg.h"
#include "debug.h"

USART2_RECEIVETYPE Usart2_Type;
USART2_RECEIVETYPE usart2_rx;
extern osMessageQueueId_t myQueue02Handle;
extern osSemaphoreId_t myBinarySem01Handle;

struct cmd_para cmd_para_st = { 0xff };
struct Model_WorkState module_status;
RX_receiveState receive_state;

struct aliyun aliyun_para;

#define BUFF_TX_LEN (1024)
uint8_t buff_cmd[BUFF_TX_LEN] = { 0 };
uint8_t buff_tx[BUFF_TX_LEN] = { 0 };

void USART2_RxIdleCallback(UART_HandleTypeDef *huart)
{
	if ((__HAL_UART_GET_FLAG(huart,UART_FLAG_IDLE) != RESET)) {
		__HAL_UART_CLEAR_IDLEFLAG(huart);
		HAL_UART_DMAStop(huart);
		Usart2_Type.RX_Size = USART2_LEN - huart->hdmarx->Instance->NDTR;
		/************************************************************************************/
		if (Usart2_Type.RX_Size <= USART2_LEN)
			osMessageQueuePut(myQueue02Handle, &Usart2_Type, 0U, 0U);
//		HAL_UART_Transmit(&huart3, &Usart2_Type.RX_pData[0], Usart2_Type.RX_Size, 0xFFFF);
		memset(&Usart2_Type.RX_pData, 0x00, Usart2_Type.RX_Size);
		/************************************************************************************/
		__HAL_UART_CLEAR_OREFLAG(huart);
		HAL_UART_Receive_DMA(huart, &Usart2_Type.RX_pData[0], USART2_LEN);
	}
}
void usart2_rx_deal(USART2_RECEIVETYPE *usart2_rx)
{
	HAL_UART_Transmit(&huart3, &usart2_rx->RX_pData[0], usart2_rx->RX_Size, 0xFFFF);
	char *str1 = NULL;
	char *str2 = NULL;
	str1 = (char*) usart2_rx->RX_pData;
	for (uint8_t i = 0; i < cmd_para_st.arg_num; i++) {
		str2 = strstr(str1, &cmd_para_st.key_char[i][0]);
		if (str2 != NULL) {
			osSemaphoreRelease(myBinarySem01Handle);
		}
	}
}

uint8_t mod_cmd_check(char *cmd, uint32_t ms, uint8_t arg_num, ...)
{
	uint8_t ret = 0;
	/******************************************/
	/* 1.va_list */
	va_list var_arg;
	int array[arg_num];
	/* 2.var_arg */
	va_start(var_arg, arg_num);
	for (uint8_t i = 0; i < arg_num; i++) {
		/* 3.va_arg */
		array[i] = va_arg(var_arg, int);
	}
	/******************************************/
	cmd_para_st.arg_num = arg_num;
	memset(&cmd_para_st.key_char[0][0], 0x00, sizeof(cmd_para_st.key_char[CHAR_NUM][CHAR_LEN]));
	for (uint8_t i = 0; (i < arg_num) && (arg_num <= CHAR_NUM); i++) {
		memcpy(&cmd_para_st.key_char[i][0], (char*) array[i], CHAR_LEN);
	}
	memset(buff_tx, 0x00, BUFF_TX_LEN);
	memcpy((char*) buff_tx, cmd, strlen(cmd));
	HAL_UART_Transmit(&huart2, buff_tx, strlen((char*) buff_tx), 0xFFFF);
	if (osOK == osSemaphoreAcquire(myBinarySem01Handle, ms))
		ret = HAL_OK;
	else {
		if (arg_num == 0)
			ret = HAL_OK;
		else
			ret = HAL_ERROR;
	}
	/******************************************/
	/* 4.va_end */
	va_end(var_arg);
	/******************************************/
	return ret;
}

uint8_t mod_para_init(void)
{
	char *ProductKey = { "a1bmBMfSgEy" };
	char *DeviceName = { "gate" };
	char *DeviceSecret = { "b0f0ccd0ff12ec0c23ed956db60bd4b7" };

	memcpy(aliyun_para.productKey, ProductKey, strlen(ProductKey));
	memcpy(aliyun_para.deviceName, DeviceName, strlen(DeviceName));
	memcpy(aliyun_para.deviceSecret, DeviceSecret, strlen(DeviceSecret));
}
uint8_t mod_read_status(void)
{
	uint8_t ret = HAL_GPIO_ReadPin(EC600_STATUS_GPIO_Port, EC600_STATUS_Pin);
	return ret;
}
void mod_operate_power(void)
{
	HAL_GPIO_WritePin(EC600_PWR_GPIO_Port, EC600_PWR_Pin, GPIO_PIN_RESET);
	osDelay(2000);
	HAL_GPIO_WritePin(EC600_PWR_GPIO_Port, EC600_PWR_Pin, GPIO_PIN_SET);
	osDelay(2000);
}
uint8_t mod_open_power(void)
{
	DEBUG_L("Opening the module-power! \r\n");
	mod_operate_power();
	for(int cnt = 0; cnt <= 30; cnt++) {
		if(mod_read_status() != 0) {
			DEBUG_L("Opening the module-power! \r\n");
			mod_operate_power();
		}else {
			DEBUG_L("Open the module-power successful! \r\n");
			return HAL_OK;
		}

	}
	DEBUG_L("Open the module-power failed! \r\n");
	return HAL_ERROR;
}
Mod_Status mod_get_conn(void)
{
	for (int i = 0; i < 3; i++) {
		if (mod_cmd_check("AT+CGMI\r\n", 1000, 1, "OK") == 0) {
			DEBUG_L("Connected to module successful! \r\n");
			return Normal;
		}
	}
	DEBUG_L("Connected to module failed! \r\n");
	return Failure;
}
void mod_reset(void)
{

}

void mqtt_init(void)
{
	mod_cmd_check("ATE1\r\n", 1000, 0);
	mod_cmd_check("ATI\r\n", 1000, 0);
	mod_cmd_check("AT+QSCLK=0\r\n", 1000, 0);
	mod_cmd_check("AT+CTZU=3\r\n", 1000, 0);
	mod_cmd_check("AT+CGSN\r\n", 3000, 1, "OK");
	mod_cmd_check("AT+CIMI\r\n", 3000, 1, "OK");
	mod_cmd_check("AT+COPS?\r\n", 3000, 1, "OK");
	mod_cmd_check("AT+CSQ\r\n", 3000, 1, "OK");
	mod_cmd_check("AT+CGPADDR\r\n", 3000, 1, "OK");
	mod_cmd_check("AT+CPIN?\r\n", 1000, 1, "OK");

	mod_cmd_check("AT+CEREG=2\r\n", 1000, 0);
	mod_cmd_check("AT+CEREG?\r\n", 3000, 1, "+CEREG: 2,1");
}
Mod_Status mqtt_CGATT(void)
{
	mod_cmd_check("AT+CGATT=1\r\n", 3000, 1, "OK");
	receive_state.CGATT = NOT;
	for (int i = 0; i < 3; i++) {
		if (mod_cmd_check("AT+CGATT?\r\n", 2000, 1, "+CGATT: 1") == 0) {

			receive_state.CGATT = CORRECT;
			return Normal;
		}
	}
	return Failure;
}
Mod_Status mqtt_CEREG(void)
{
	receive_state.CEREG = NOT;
	for (int i = 0; i < 3; i++) {
		if (mod_cmd_check("AT+CEREG?\r\n", 3000, 0) == 0) {
			receive_state.CEREG = CORRECT;
			return Normal;
		} else {
			mod_cmd_check("AT+CEREG=2\r\n", 1000, 0);
		}
	}
	return Failure;
}
Mod_Status mqtt_NetClock(void)
{
	receive_state.CCLK = NOT;
	if (mod_cmd_check("AT+CCLK?\r\n", 2000, 0) == 0) {
		receive_state.CCLK = CORRECT;
		return Normal;
	}
	return Failure;
}
Mod_Status mqtt_release(void)
{
	mod_cmd_check("AT+QMTCLOSE=0\r\n", 3000, 0);
	return Normal;
}

Mod_Status message(void)
{
	mod_cmd_check("AT+CSMS=?\r\n", 3000, 0);
	mod_cmd_check("AT+CSMS?\r\n", 3000, 0);
	mod_cmd_check("AT+CMGF=1\r\n", 3000, 0);
	mod_cmd_check("AT+CMGS=\"17842240824\"\r\n", 3000, 1, ">");

	memset((char*) buff_cmd, 0x00, BUFF_TX_LEN);
	sprintf((char*) buff_cmd, "%s", "hello world!");
	HAL_UART_Transmit(&huart2, (char*) buff_cmd, strlen(buff_cmd), 1000);
	uint8_t end = 0x1a;
	HAL_UART_Transmit(&huart2, &end, 1, 1000);
}
Mod_Status mqtt_aliyun_conn(void)
{
	memset((char*) buff_cmd, 0x00, BUFF_TX_LEN);
	sprintf((char*) buff_cmd, "AT+QMTCFG=\"aliauth\",0,\"%s\",\"%s\",\"%s\"\r\n", aliyun_para.productKey,
			aliyun_para.deviceName, aliyun_para.deviceSecret);
	if (0 != mod_cmd_check((char*) buff_cmd, 5000, 1, "OK"))
		return Failure;

	if (0
			== mod_cmd_check("AT+QMTOPEN=0,\"iot-as-mqtt.cn-shanghai.aliyuncs.com\",1883\r\n", 5000, 1,
					"+QMTOPEN: 0,0")) {
		receive_state.QMTOPEN = CORRECT;
	} else {
		return Failure;
	}

	memset((char*) buff_cmd, 0x00, BUFF_TX_LEN);
	sprintf((char*) buff_cmd, "AT+QMTCONN=0,\"%s\"\r\n", aliyun_para.deviceName);
	if (0 == mod_cmd_check((char*) buff_cmd, 5000, 1, "+QMTCONN: 0,0,0")) {
		receive_state.QMTCONN = CORRECT;
	} else {
		return Failure;
	}

	mod_cmd_check("AT+QIDNSCFG=1,223.5.5.5,223.6.6.6\r\n", 1000, 0);
	return Normal;
}

void node_register(void)
{

	osDelay(5000);
	uint8_t end = 0x1a;
	int len = 0;
	char *node = {
		"\
		{\
		  \"id\": \"123\",\
		  \"version\": \"1.0\",\
		  \"sys\":{\
			  \"ack\":0\
		  },\
		  \"params\": [\
			{\
			  \"deviceName\": \"Solenoid_valve1\",\
			  \"productKey\": \"a16PUVbTfGt\"\
			}\
		  ],\
		  \"method\": \"thing.sub.register\"\
		}\
		"
	};
	len = strlen(node);
	memset((char*) buff_cmd, 0x00, BUFF_TX_LEN);
	sprintf((char*) buff_cmd, "AT+QMTPUBEX=0,0,0,0,\"/sys/%s/%s/thing/sub/register\",%d\r\n",
			aliyun_para.productKey, aliyun_para.deviceName, len);
	if (0 != mod_cmd_check((char*) buff_cmd, 5000, 1, ">")) {
		return;
	}


	HAL_UART_Transmit(&huart2, (char*) node, strlen(node), 3000);
	HAL_UART_Transmit(&huart2, &end, 1, 3000);


}
void node_topo_add(void)
{

	osDelay(5000);
	uint8_t end = 0x1a;
	int len = 0;

	char *node = {
		"\
		{\
		  \"id\": \"123\",\
		  \"version\": \"1.0\",\
		  \"sys\":{\
			  \"ack\":0\
		  },\
		  \"params\": [\
			{\
			  \"deviceName\": \"Solenoid_valve1\",\
			  \"productKey\": \"a16PUVbTfGt\",\
			  \"sign\": \"3bcc20d7d3688bf4e563c74c45ec2f5a9b1ce7f0\",\
			  \"signmethod\": \"hmacSha1\",\
			  \"timestamp\": \"1524448722000\",\
			  \"clientId\": \"123\"\
			}\
		  ],\
		  \"method\": \"thing.topo.add\"\
		}\
		"
	};
	len = strlen(node);

	memset((char*) buff_cmd, 0x00, BUFF_TX_LEN);
	sprintf((char*) buff_cmd, "AT+QMTPUB=0,0,0,0,\"/sys/%s/%s/thing/topo/add_reply\",%d\r\n",
			aliyun_para.productKey, aliyun_para.deviceName, len);
	if (0 != mod_cmd_check((char*) buff_cmd, 5000, 1, ">")) {
		return;
	}


	HAL_UART_Transmit(&huart2, (char*) node, strlen(node), 3000);
	HAL_UART_Transmit(&huart2, &end, 1, 3000);

}
void node_online(void)
{

	osDelay(5000);
	uint8_t end = 0x1a;
	int len = 0;

	char *node = {
		"{\
			\"id\": \"123\",\
			\"params\": {\
			\"productKey\": \"a16PUVbTfGt\",\
			\"deviceName\": \"Solenoid_valve1\",\
			\"clientId\": \"a16PUVbTfGt&Solenoid_valve1\",\
			\"timestamp\": \"1581417203000\",\
			\"signMethod\": \"hmacmd5\",\
			\"sign\": \"f6f089cb7e05a51a8d44f04435ad84ae\",\
			\"cleanSession\": \"true\"\
			}\
		}"
	};
	len = strlen(node);

	memset((char*) buff_cmd, 0x00, BUFF_TX_LEN);
	sprintf((char*) buff_cmd, "AT+QMTPUBEX=0,0,0,0,\"/ext/session/%s/%s/combine/login\",%d\r\n",
			aliyun_para.productKey, aliyun_para.deviceName, len);
	if (0 != mod_cmd_check((char*) buff_cmd, 5000, 1, ">")) {
		return;
	}

	HAL_UART_Transmit(&huart2, (char*) node, strlen(node), 3000);
	HAL_UART_Transmit(&huart2, &end, 1, 3000);
}

void node_offline(void)
{

	osDelay(5000);
	uint8_t end = 0x1a;
	int len = 0;

	char *node = {
		"{\
			\"id\": \"123\",\
			\"params\": {\
			\"productKey\": \"a16PUVbTfGt\",\
			\"deviceName\": \"Solenoid_valve1\",\
			\"clientId\": \"a16PUVbTfGt&Solenoid_valve1\",\
			\"timestamp\": \"1581417203000\",\
			\"signMethod\": \"hmacmd5\",\
			\"sign\": \"f6f089cb7e05a51a8d44f04435ad84ae\",\
			\"cleanSession\": \"true\"\
			}\
		}"
	};
	len = strlen(node);

	memset((char*) buff_cmd, 0x00, BUFF_TX_LEN);
	sprintf((char*) buff_cmd, "AT+QMTPUBEX=0,0,0,0,\"/ext/session/%s/%s/combine/login\",%d\r\n",
			aliyun_para.productKey, aliyun_para.deviceName, len);
	if (0 != mod_cmd_check((char*) buff_cmd, 5000, 1, ">")) {
		return;
	}

	HAL_UART_Transmit(&huart2, (char*) node, strlen(node), 3000);
	HAL_UART_Transmit(&huart2, &end, 1, 3000);
}
void node_data_sub(void)
{
	osDelay(5000);
	uint8_t end = 0x1a;
	int len = 0;

	char *node = {
		"{\
			  \"id\": \"123\",\
			  \"version\": \"1.0\",\
			  \"sys\":{\
				  \"ack\":0\
			  },\
			  \"params\": {\
				\"voltage\": {\
				  \"value\": 2345\
				}\
			  },\
			  \"method\": \"thing.event.property.post\"\
		}"
	};
	len = strlen(node);

	memset((char*) buff_cmd, 0x00, BUFF_TX_LEN);
	sprintf((char*) buff_cmd, "AT+QMTPUBEX=0,0,0,0,\"/sys/%s/%s/thing/event/property/post\",%d\r\n",
			"a16PUVbTfGt", "Solenoid_valve1", len);
	if (0 != mod_cmd_check((char*) buff_cmd, 5000, 1, ">")) {
		return;
	}

	HAL_UART_Transmit(&huart2, (char*) node, strlen(node), 3000);
	HAL_UART_Transmit(&huart2, &end, 1, 3000);




}
void mod_sub(void)
{
	uint8_t end = 0x1a;
	int len = 0;
	memset((char*) buff_cmd, 0x00, BUFF_TX_LEN);
	sprintf((char*) buff_cmd, "AT+QMTSUB=0,1,\"%s/%s/user/get\",0 \r\n", aliyun_para.productKey,
			aliyun_para.deviceName);
	if (0 != mod_cmd_check((char*) buff_cmd, 5000, 1, "+QMTSUB: 0,1,0,1")) {
	}

	memset((char*) buff_cmd, 0x00, BUFF_TX_LEN);
	sprintf((char*) buff_cmd,"{params:{%s:%s}}","temperature","21.35");
	len = strlen(buff_cmd);

	memset((char*) buff_cmd, 0x00, BUFF_TX_LEN);
	sprintf((char*) buff_cmd, "AT+QMTPUBEX=0,0,0,0,\"/sys/%s/%s/thing/event/property/post\",%d\r\n",
			aliyun_para.productKey, aliyun_para.deviceName, len);
	if (0 != mod_cmd_check((char*) buff_cmd, 5000, 1, ">")) {
	}

	memset((char*) buff_cmd, 0x00, BUFF_TX_LEN);
	sprintf((char*) buff_cmd,"{params:{%s:%s}}%c","temperature","21.35",0x1a);
	HAL_UART_Transmit(&huart2, (char*) buff_cmd, strlen(buff_cmd), 3000);
}
void mod_deal(void)
{

	mod_para_init();
	re_run:
	/*wait power steady*/
	DEBUG_L("Wait power steady about 2s!\r\n");
	osDelay(2000);
	/*power*/
	mod_open_power();
	DEBUG_L("Wait module initial finished about 10s!\r\n");
	osDelay(10000);
	/*check connection with module*/
	module_status.ModelToMCU = mod_get_conn();
	if(module_status.ModelToMCU != Normal) {
		mod_reset();
		goto re_run;
	}
	/********************************************/
	mqtt_init();
	module_status.NetRegister = mqtt_CGATT();
	mqtt_release();
	if (module_status.NetRegister == Normal) {
		module_status.MqttConnect = mqtt_aliyun_conn();
		module_status.NetAddr = mqtt_CEREG();
		module_status.NetClock = mqtt_NetClock();
	}
	mod_sub();
//	node_register();
//	node_topo_add();
	node_online();
	node_data_sub();
	node_data_sub();
//	message();
	/********************************************/
while(1){}
}
